// import { newInstance } from './../../../views/project/modules/VpuPart/GlanceZipObjReader';
// import macro from '@kitware/vtk.js/macro';
import macro from '@kitware/vtk.js/macro';
// import _defineProperty from '@babel/runtime/helpers/defineProperty';
import vtkMatrixBuilder from '@kitware/vtk.js/Common/Core/MatrixBuilder';
import vtkDataArray from '@kitware/vtk.js/Common/Core/DataArray';
// import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
import vtkAnnotatedCubeActor from '@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor';
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
import vtkArrowSource from '@kitware/vtk.js/Filters/Sources/ArrowSource';
import vtkAppendPolyData from '@kitware/vtk.js/Filters/General/AppendPolyData';
import vtkCubeSource from '@kitware/vtk.js/Filters/Sources/CubeSource';
import vtkTexture from '@kitware/vtk.js/Rendering/Core/Texture.js';
// import vtkOpenGLRenderWindow from 'vtk.js/Sources/Rendering/OpenGL/RenderWindow';
import vtkCubeAxesActor from '@kitware/vtk.js/Rendering/Core/CubeAxesActor';
// import AnnotatedCubePresets from '@kitware/vtk.js/Rendering/Core/AnnotatedCubeActor/Presets.js';
import '@kitware/vtk.js/favicon';
// import vtkPixelSpaceCallbackMapper from '@kitware/vtk.js/Rendering/Core/PixelSpaceCallbackMapper';
// Load the rendering pieces we want to use (for both WebGL and WebGPU)
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
import '@kitware/vtk.js/Rendering/Profiles/Molecule'; // for vtkSphereMapper
// import vtkSphereMapper from '@kitware/vtk.js/Rendering/Core/SphereMapper';
import ImageHelper from '@kitware/vtk.js/Common/Core/ImageHelper.js';
// import style from './style.module.css';
import Constants from './Constants';
//VTK.js Orientation Indicator
function getMousePos(canvas, event) {
  const rect = canvas.getBoundingClientRect();
  return {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top,
  };
}
function isInside(pos, rect) {
  return (
    pos.x > rect.x && pos.x < rect.x + rect.width && pos.y < rect.y + rect.height && pos.y > rect.y
  );
}
// CustomAxesActor
// const container = document.createElement('div');
// const dims: { width: number; height: number } = container.getBoundingClientRect();
const cubeSource = vtkCubeSource
  .newInstance({
    generate3DTextureCoordinates: false,
    xLength: 1,
    yLength: 1,
    zLength: 1,
  })
  .getOutputData();
// ----------------------------------------------------------------------------

const FACE_TO_INDEX = {
  xPlus: 0,
  xMinus: 1,
  yPlus: 2,
  yMinus: 3,
  zPlus: 4,
  zMinus: 5,
};
function centerDataSet(ds) {
  const bounds = ds.getPoints().getBounds();
  const center = [
    -(bounds[0] + bounds[1]) * 0.5,
    -(bounds[2] + bounds[3]) * 0.5,
    -(bounds[4] + bounds[5]) * 0.5,
  ];
  vtkMatrixBuilder
    .buildFromDegree()
    //@ts-ignore
    .translate(...center)
    .apply(ds.getPoints().getData());
}

// ----------------------------------------------------------------------------

function addColor(ds, r, g, b) {
  const size = ds.getPoints().getData().length;
  const rgbArray = new Uint8Array(size);
  let offset = 0;

  while (offset < size) {
    rgbArray[offset++] = r;
    rgbArray[offset++] = g;
    rgbArray[offset++] = b;
  }

  ds.getPointData().setScalars(
    vtkDataArray.newInstance({
      name: 'color',
      numberOfComponents: 3,
      values: rgbArray,
    }),
  );
}
//
function addColorb(ds, r, g, b) {
  const size = ds.getPoints().getData().length;
  const rgbArray = new Uint8Array(size);
  let offset = 0;

  while (offset < size) {
    rgbArray[offset++] = r;
    rgbArray[offset++] = g;
    rgbArray[offset++] = b;
  }

  ds.getPointData().setScalars(
    vtkDataArray.newInstance({
      name: 'color',
      numberOfComponents: 3,
      values: rgbArray,
    }),
  );
}
// function attachText(axis) {
//   container.classList.add(style.container);
//   document.querySelector('body')!.appendChild(container);
//   const textCanvas = document.createElement('canvas');
//   textCanvas.classList.add(style.container, 'textCanvas');
//   const textCtx = textCanvas.getContext('2d');

//   const mapper = vtkSphereMapper.newInstance();
//   mapper.setInputConnection(axis);
//   const psMapper = vtkPixelSpaceCallbackMapper.newInstance();
//   psMapper.setInputConnection(axis);
//   //@ts-ignore
//   psMapper.setCallback((coordsList) => {
//     if (textCtx && dims) {
//       textCtx.clearRect(0, 0, dims.width, dims.height);
//       coordsList.forEach((xy, idx) => {
//         textCtx.font = '12px serif';
//         textCtx.textAlign = 'center';
//         textCtx.textBaseline = 'middle';
//         textCtx.fillText(`p ${idx}`, xy[0], dims.height - xy[1]);
//       });
//     }
//   });
// }
// ----------------------------------------------------------------------------
// CustomAxesActor
// ----------------------------------------------------------------------------

function CustomAxesActor(publicAPI, model) {
  // Set our className
  // model.classHierarchy.push('CustomAxesActor');

  publicAPI.update = () => {
    const xAxis = vtkArrowSource
      .newInstance({ direction: [1, 0, 0], ...model.config, shaftLength: 3 })
      .getOutputData();
    centerDataSet(xAxis);
    // attachText(xAxis);
    //@ts-ignore
    addColor(xAxis, ...model.xAxisColor);

    const xAxisPts = xAxis.getPoints().getData();
    vtkMatrixBuilder.buildFromRadian().translate(0.55, 0.0, 0.0).apply(xAxisPts);

    centerDataSet(cubeSource);
    const cubePts = cubeSource.getPoints().getData();
    vtkMatrixBuilder.buildFromRadian().translate(0.0, 0.0, 0.0).apply(cubePts);
    // set mapper
    const mapper = vtkMapper.newInstance();
    mapper.setInputConnection(cubeSource);
    // publicAPI.setMapper(mapper);
    //@ts-ignore
    addColorb(cubeSource, [114, 147, 222]);
    const xAxis2 = vtkArrowSource
      .newInstance({ direction: [-1, 0, 0], ...model.config, shaftLength: 3 })
      .getOutputData();
    centerDataSet(xAxis2);
    //@ts-ignore
    addColor(xAxis2, ...model.xAxisColor);
    const xAxisPts2 = xAxis2.getPoints().getData();
    vtkMatrixBuilder.buildFromRadian().translate(-0.55, 0.0, 0.0).apply(xAxisPts2);

    const yAxis = vtkArrowSource
      .newInstance({ direction: [0, 1, 0], ...model.config })
      .getOutputData();
    centerDataSet(yAxis);
    //@ts-ignore
    addColor(yAxis, ...model.yAxisColor);

    const yAxisPts = yAxis.getPoints().getData();
    vtkMatrixBuilder.buildFromRadian().translate(0.0, 0.55, 0.0).apply(yAxisPts);

    const zAxis = vtkArrowSource
      .newInstance({ direction: [0, 0, 1], ...model.config })
      .getOutputData();
    centerDataSet(zAxis);
    //@ts-ignore
    addColor(zAxis, ...model.zAxisColor);

    const zAxisPts = zAxis.getPoints().getData();
    vtkMatrixBuilder.buildFromRadian().translate(0.0, 0.0, 0.55).apply(zAxisPts);

    const source = vtkAppendPolyData.newInstance();
    source.setInputData(xAxis);
    source.addInputData(xAxis2);
    source.setInputData(cubeSource);
    source.addInputData(yAxis);
    source.addInputData(zAxis);
  };
  // publicAPI.getSources = () => [].concat(cubeSource || []);
  // publicAPI.getRepresentations = () => [].concat(model.proxyByGroup.Representations || []);
  // publicAPI.getViews = () => [].concat(model.proxyByGroup.Views || []);

  publicAPI.update();
}

// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------

export const DEFAULT_VALUES = {
  config: {
    tipResolution: 60,
    tipRadius: 0.06,
    tipLength: 0.1,
    shaftResolution: 60,
    shaftRadius: 0.01,
    invert: false,
  },
  xAxisColor: [88, 124, 209],
  yAxisColor: [148, 212, 167],
  zAxisColor: [224, 141, 79],
  cubeColor: [244, 141, 33],
};
// const debugCanvasSize = 1 / 4;
// const dbgWidth = 0;
// const dbgHeight = 0;
// const lastDepthBuffer = null;
// ----------------------------------------------------------------------------
const canvas = document.createElement('canvas');
// canvas.addEventListener('click', (evt) => {
// evt.preventDefault();
// evt.stopPropagation();
// const x = (evt.pageX - canvas.offsetLeft) / debugCanvasSize;
// const y = (evt.pageY - canvas.offsetTop) / debugCanvasSize;
// if (lastDepthBuffer && dbgWidth > 0 && dbgHeight > 0) {
//   const dIdx = ((dbgHeight - 1 - Math.floor(y)) * dbgWidth + Math.floor(x)) * 4;
//   const r = lastDepthBuffer[dIdx] / 255;
//   const g = lastDepthBuffer[dIdx + 1] / 255;
//   let z = (r * 256 + g) / 257;
//   z = z * 2 - 1; // scale depths from [0, 1] into [-1, 1]
//   alert(`depth at::::::::: (${x}, ${y}) is ${z}`);
// } else {
//   alert('bbbbbbbbb');
// }
// });
canvas.addEventListener(
  'click',
  function (evt) {
    const mousePos = getMousePos(canvas, evt);

    const rect = {
      x: 250,
      y: 350,
      width: 200,
      height: 100,
    };
    if (isInside(mousePos, rect)) {
      alert('clicked inside rect');
    } else {
      alert('clicked outside rect');
    }
  },
  false,
);
// const mapper = vtkMapper.newInstance();
const texture = vtkTexture.newInstance();
texture.setInterpolate(true); // private methods
let prop = {
  text: '前',
  faceColor: '#7293DE',
  faceRotation: 0,
  fontFamily: 'Arial',
  fontColor: '#FFFFFF',
  fontStyle: 'normal',
  fontSizeScale: function fontSizeScale(resolution) {
    return resolution / 1.8;
  },
  edgeThickness: 0.1,
  edgeColor: 'black',
  resolution: 250,
};
//https://stackoverflow.com/questions/808826/draw-arrow-on-canvas-tag
function canvas_arrow(context, fromx, fromy, tox, toy, r) {
  const x_center = tox;
  const y_center = toy;

  let angle;
  let x;
  let y;

  context.beginPath();

  angle = Math.atan2(toy - fromy, tox - fromx);
  x = r * Math.cos(angle) + x_center;
  y = r * Math.sin(angle) + y_center;

  context.moveTo(x, y);

  angle += (1 / 3) * (2 * Math.PI);
  x = r * Math.cos(angle) + x_center;
  y = r * Math.sin(angle) + y_center;

  context.lineTo(x, y);

  angle += (1 / 3) * (2 * Math.PI);
  x = r * Math.cos(angle) + x_center;
  y = r * Math.sin(angle) + y_center;

  context.lineTo(x, y);

  context.closePath();

  context.fill();
}
function canvas_arrowb(context, fromx, fromy, tox, toy) {
  const headlen = 10; // length of head in pixels
  const dx = tox - fromx;
  const dy = toy - fromy;
  const angle = Math.atan2(dy, dx);
  context.moveTo(fromx, fromy);
  context.lineTo(tox, toy);
  context.lineTo(
    tox - headlen * Math.cos(angle - Math.PI / 6),
    toy - headlen * Math.sin(angle - Math.PI / 6),
  );
  context.moveTo(tox, toy);
  context.lineTo(
    tox - headlen * Math.cos(angle + Math.PI / 6),
    toy - headlen * Math.sin(angle + Math.PI / 6),
  );
}
function updateFaceTexture(faceName, prop) {
  try {
    // const newProp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;

    // if (newProp) {
    //   // Object!.assign(model["".concat(faceName, "FaceProperty")], newProp);
    // }

    canvas.width = 350;
    canvas.height = 350;
    const ctxt = canvas.getContext('2d'); // set background color

    ctxt!.fillStyle = '#7293DE';
    ctxt!.fillRect(0, 0, canvas.width, canvas.height); // draw edge

    ctxt!.strokeStyle = '#7293DE';
    ctxt!.lineWidth = 0.1 * canvas.width;
    ctxt!.strokeRect(0, 0, canvas.width, canvas.height);

    ctxt!.save(); // vertical flip

    ctxt!.translate(0, canvas.height);
    ctxt!.scale(1, -1);
    ctxt!.translate(canvas.width / 2, canvas.height / 2);
    ctxt!.rotate(-Math.PI * (0 / 180.0)); // set foreground text

    const textSize = prop.fontSizeScale(250);
    ctxt!.fillStyle = prop.fontColor;
    ctxt!.textAlign = 'center';
    ctxt!.textBaseline = 'middle';
    ctxt!.font = ''
      .concat(prop.fontStyle, ' ')
      .concat(textSize.toString(), 'px "')
      .concat(prop.fontFamily, '"');
    ctxt!.fillText(prop.text, 0, 0);

    // ctxt!.beginPath();
    // canvas_arrow(ctxt!, 10, 30, 200, 150);
    // canvas_arrow(ctxt!, 100, 200, 400, 50);
    // canvas_arrow(ctxt!, 200, 30, 10, 150);
    // canvas_arrow(ctxt!, 400, 200, 100, 50);
    // ctxt!.stroke();
    ctxt!.lineWidth = 10;
    ctxt!.strokeStyle = 'red';
    ctxt!.fillStyle = 'red'; // for the triangle fill
    // ctxt!.lineJoin = 'butt';

    ctxt!.beginPath();
    ctxt!.moveTo(50, 50);
    ctxt!.lineTo(150, 150);
    ctxt!.stroke();

    canvas_arrow(ctxt!, 50, 50, 150, 150, 10);
    canvas_arrow(ctxt!, 150, 150, 50, 50, 10);
    canvas_arrowb(ctxt!, 100, 200, 400, 50);
    ctxt!.restore();
    const vtkImage = ImageHelper.canvasToImageData(canvas);
    texture.setInputData(vtkImage, FACE_TO_INDEX[faceName]);
  } catch (ex) {
    console.log('updateFaceTexture error:', ex);
  }
}
//
export function extend(publicAPI, model, initialValues = {}) {
  Object.assign(model, DEFAULT_VALUES, initialValues);
  model.tmActor = vtkCubeAxesActor.newInstance();
  model.tmMapper = vtkMapper.newInstance();
  model.tmTexture = vtkTexture.newInstance();
  model.tmTexture.setInterpolate(false);
  model.tmActor.setMapper(model.tmMapper);
  model.tmActor.addTexture(model.tmTexture);
  publicAPI.getActors = () => [model.tmActor];

  publicAPI.getNestedProps = () => publicAPI.getActors();

  // mapper.setInputConnection(cubeSource);
  prop = {
    text: '前',
    faceColor: '#7293DE',
    faceRotation: 0,
    fontFamily: 'Arial',
    fontColor: '#FFFFFF',
    fontStyle: 'normal',
    fontSizeScale: function fontSizeScale(resolution) {
      return resolution / 1.8;
    },
    edgeThickness: 0.1,
    edgeColor: 'black',
    resolution: 250,
  };
  updateFaceTexture('xPlus', prop);
  updateFaceTexture('xMinus', prop);
  updateFaceTexture('yPlus', prop);
  updateFaceTexture('yMinus', prop);
  updateFaceTexture('zPlus', prop);
  updateFaceTexture('zMinus', prop);

  macro.setGet(publicAPI, model, ['config']);

  macro.setGetArray(
    publicAPI,
    model,
    ['xAxisColor', 'yAxisColor', 'zAxisColor', 'cubeColor'],
    3,
    255,
  );

  function updateAllFaceTextures() {
    const mprop = {
      text: '前',
      faceColor: '#7293DE',
      faceRotation: 0,
      fontFamily: 'Arial',
      fontColor: '#FFFFFF',
      fontStyle: 'normal',
      fontSizeScale: function fontSizeScale(resolution) {
        return resolution / 1.8;
      },
      edgeThickness: 0.1,
      edgeColor: 'black',
      resolution: 250,
    };
    // cubeSource = vtkCubeSource.newInstance({
    //   generate3DTextureCoordinates: true,
    // });

    // mapper.setInputConnection(cubeSource.getOutputPort());

    updateFaceTexture('xPlus', mprop);
    updateFaceTexture('xMinus', mprop);
    updateFaceTexture('yPlus', mprop);
    updateFaceTexture('yMinus', mprop);
    updateFaceTexture('zPlus', mprop);
    updateFaceTexture('zMinus', mprop);
  }

  publicAPI.setDefaultStyle = (style) => {
    model.defaultStyle = { ...model.defaultStyle, ...style };
    updateAllFaceTextures();
  };

  publicAPI.setXPlusFaceProperty = (prop) => updateFaceTexture('xPlus', prop);
  publicAPI.setXMinusFaceProperty = (prop) => updateFaceTexture('xMinus', prop);
  publicAPI.setYPlusFaceProperty = (prop) => updateFaceTexture('yPlus', prop);
  publicAPI.setYMinusFaceProperty = (prop) => updateFaceTexture('yMinus', prop);
  publicAPI.setZPlusFaceProperty = (prop) => updateFaceTexture('zPlus', prop);
  publicAPI.setZMinusFaceProperty = (prop) => updateFaceTexture('zMinus', prop);
  // Inheritance
  vtkAnnotatedCubeActor.extend(publicAPI, model, initialValues);
  // Object methods
  CustomAxesActor(publicAPI, model);
}
function moduleScopedStaticMethod() {
  // do more stuff
}

// ----------------------------------------------------------------------------
// Static API
// ----------------------------------------------------------------------------

export const STATIC = {
  moduleScopedStaticMethod,
};

// ----------------------------------------------------------------------------

export const newInstance = macro.newInstance(extend, 'CustomAxesActor');

// ----------------------------------------------------------------------------
export default Object.assign({ newInstance, extend }, STATIC, Constants);
